#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>

#include <stdlib.h>
#include "inc/page.h"


void *allocate_new_page(size_t size) {
  return allocate_mmap_pages(1);
}

void init_page(void *page, size_t alloc_size) {
  if (page != NULL) {
    struct page_header *ptr  = page;
    memset(page, 0, sizeof(struct page_header));
    ptr->size = alloc_size;
  }
}

void init_large_page(void *page, size_t alloc_size) {
  if (page != NULL) {
    struct large_page_header *ptr = page;
    ptr->size = LARGE_PAGE_MARKER|alloc_size;
  }
}

void *allocate_mmap_pages(size_t num_pages) {
  void *alloc_addr  = mmap(NULL, num_pages*PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
  if ((void *)-1 == alloc_addr)
    return NULL;
  else
    return alloc_addr;
}

void free_mmap_pages(void *ptr, size_t num_pages) {
  if (ptr)
    munmap(ptr, num_pages*PAGE_SIZE);
}

void *allocate_remap_pages(void *ptr, size_t new_size) {
  struct large_page_header *base  = ROUNDDOWN(ptr);
  void *ret_ptr = NULL;

  if (base) {
    if(!(ret_ptr=malloc(new_size*PAGE_SIZE))) {
      free(ptr);
      return ret_ptr;
    }
    memcpy(ret_ptr, ptr, REMOVE_LARGE_PAGE_MARKER(base->size)*PAGE_SIZE); 
    free(ptr);
  }
  return ret_ptr;
}
